package org.wheel.plugins.toolkit.sql.segment;

import cn.hutool.core.collection.CollUtil;
import org.wheel.plugins.toolkit.sql.core.AbstractWrapper;
import org.wheel.plugins.toolkit.sql.core.SqlSegment;
import org.wheel.plugins.toolkit.sql.core.Wrapper;
import org.wheel.plugins.toolkit.sql.helper.AliasRegistry;
import org.wheel.plugins.toolkit.sql.helper.LambdaUtils;
import org.wheel.plugins.toolkit.sql.helper.SFunction;

import java.util.List;
import java.util.Map;

/**
 * 窗口函数 – OVER(PARTITION BY … ORDER BY …) 构造器
 */
public final class SqlWindowUnit implements SqlSegment {

    private final List<String> partitionBy = CollUtil.newArrayList();
    private final List<String> orderBy = CollUtil.newArrayList();
    private final AbstractWrapper<?, ?> wrapper;   // 用于自动别名

    public SqlWindowUnit(AbstractWrapper<?, ?> wrapper) {
        this.wrapper = wrapper;
    }

    /* ========== 自动别名 – Lambda 字段 ========== */
    @SafeVarargs
    public final <T> SqlWindowUnit partitionBy(SFunction<T, ?>... columns) {
        String tableAlias = wrapper.getMainAlias();
        Class<?> entityClass = LambdaUtils.getCapturingClass(columns[0]);
        if(wrapper != null && this.wrapper.getContext().getAliasRegistry().isRegister(entityClass)){
            tableAlias = this.wrapper.getContext().getAliasRegistry().resolveAlias(entityClass);
        }
        return partitionBy(tableAlias, columns);
    }
    @SafeVarargs
    public final <T> SqlWindowUnit orderByDesc(SFunction<T, ?>... columns) {
        String tableAlias = null;
        if(this.wrapper == null){
            Class<?> entityClass = LambdaUtils.getCapturingClass(columns[0]);
            if(wrapper != null && this.wrapper.getContext().getAliasRegistry().isRegister(entityClass)){
                tableAlias = this.wrapper.getContext().getAliasRegistry().resolveAlias(entityClass);
            }
        }else{
            tableAlias = wrapper.getMainAlias();
        }
        return orderByDesc(tableAlias, columns);
    }
    @SafeVarargs
    public final <T> SqlWindowUnit orderByAsc(SFunction<T, ?>... columns) {
        return orderByAsc(wrapper.getMainAlias(), columns);
    }

    /* ========== 显式别名 – Lambda 字段 ========== */
    public final SqlWindowUnit partitionBy(String alias, SFunction<?, ?>... columns) {
        for (SFunction<?, ?> fn : columns) {
            partitionBy.add(alias + "." + LambdaUtils.getColumn(fn));
        }
        return this;
    }
    public final SqlWindowUnit orderByDesc(String alias, SFunction<?, ?>... columns) {
        for (SFunction<?, ?> fn : columns) {
            orderBy.add(alias + "." + LambdaUtils.getColumn(fn) + " DESC");
        }
        return this;
    }
    public final SqlWindowUnit orderByAsc(String alias, SFunction<?, ?>... columns) {
        for (SFunction<?, ?> fn : columns) {
            orderBy.add(alias + "." + LambdaUtils.getColumn(fn) + " ASC");
        }
        return this;
    }

    /* ========== 显式别名 – 字符串字段 ========== */
    public final SqlWindowUnit partitionBy(String... columns) {
        for (String col : columns) {
            partitionBy.add(col);
        }
        return this;
    }
    public final SqlWindowUnit orderByDesc(String... columns) {
        for (String col : columns) {
            orderBy.add(col + " DESC");
        }
        return this;
    }
    public final SqlWindowUnit orderByAsc(String... columns) {
        for (String col : columns) {
            orderBy.add(col + " ASC");
        }
        return this;
    }

    /* ========== 渲染 ========== */
    @Override
    public String getSql() {
        if (partitionBy.isEmpty() && orderBy.isEmpty()) return "";
        StringBuilder sb = new StringBuilder(" OVER(");
        if (!partitionBy.isEmpty()) {
            sb.append("PARTITION BY ").append(CollUtil.join(partitionBy, ", "));
        }
        if (!orderBy.isEmpty()) {
            if (!partitionBy.isEmpty()) sb.append(" ");
            sb.append("ORDER BY ").append(CollUtil.join(orderBy, ", "));
        }
        return sb.append(')').toString();
    }
}